/*
 * DungeonRewardResource.cpp
 *
 *  Created on: 2013. 9. 13.
 *      Author: mega@gamevil.com
 */

#include "../User.h"
#include "../engine.h"
#include "../NUtil/Utils.h"
#include "../NResource/Static.h"
#include "../NLogic/Space.h"
#include "../NLogic/Card.h"

#include "DungeonRewardResource.h"

namespace ProjectZ { namespace NResource {

DungeonRewardResource::DungeonRewardResource()
{
	pDungeonRewardAD	= new DungeonRewardData;
	pDungeonRewardIOS	= new DungeonRewardData;
}

DungeonRewardResource::~DungeonRewardResource()
{
	delete pDungeonRewardAD;
	delete pDungeonRewardIOS;
}

bool DungeonRewardResource::LoadResource()
{
	if (false == pDungeonRewardAD->LoadResource(MARKET_GOOGLE, SC_KAKAO_GOOGLE))
		return false;

	if (false == pDungeonRewardIOS->LoadResource(MARKET_IOS, SC_KAKAO_IOS))
		return false;

	return true;
}

DungeonRewardData::Flyweight * DungeonRewardResource::GetFly(User * pUser, DungeonRewardData::Key & clsKey)
{
	NUtil::MarketType marketType = NUtil::GetMarketType(pUser->GetUserInfo().company, pUser->GetUserInfo().sale_code);

	switch (marketType)
	{
	case NUtil::MarketType::AD_KAKAO:
		return pDungeonRewardAD->GetFly(clsKey);

	case NUtil::MarketType::IOS_KAKAO:
		return pDungeonRewardIOS->GetFly(clsKey);

	default:
		return NULL;
	}

	return NULL;
}

DungeonRewardData::~DungeonRewardData()
{
	std::for_each(clsFlyTree.begin(), clsFlyTree.end(), ProjectZ::NUtil::del_second_ptr<DUNGEONREWARDTREE::value_type>);
}

void
DungeonRewardData::Clear()
{
	std::for_each(clsFlyTree.begin(), clsFlyTree.end(), ProjectZ::NUtil::del_second_ptr<DUNGEONREWARDTREE::value_type>);
	clsFlyTree.clear();
}

bool DungeonRewardData::LoadResource(int company, int saleCode)
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::SELECT);
	clsAuto->MakeQuery("SELECT NATIONAL_CODE, type, sub_type, value1, value2, value3 FROM resource_dungeonreward WHERE company=%d AND sale_cd=%d ORDER BY type, sub_type", company, saleCode);

	if (false == ::Database::GETSESSION()->SyncExecute(1, clsAuto))
		return false;

	if( clsAuto->GetErrorIdx() != 0 )
		return false;

	if (0 == clsAuto->ResultRowCount())
		return false;

	Clear();

	while( clsAuto->Next() )
	{
		::Toolkit::Str<3> NATIONAL_CODE;
		DungeonRewardData::Flyweight * pFly = new DungeonRewardData::Flyweight;

		clsAuto->GetRecord() >> NATIONAL_CODE >> pFly->_TYPE >> pFly->_SUB_TYPE >> pFly->_VALUE1 >> pFly->_VALUE2 >> pFly->_VALUE3;

		if (0 != Config::Instance().GetResourceDatabase()._strNational.compare(NATIONAL_CODE.c_str()))
		{
			DEBUGLOG("%s:%d NATIONAL_CODE ERROR!!! Config National Code [%s] , Resource National Code [%s]",
					__FILE__, __LINE__,
					Config::Instance().GetResourceDatabase()._strNational.c_str(),
					NATIONAL_CODE.c_str());
			return false;
		}

		clsFlyTree[DungeonRewardData::Key(pFly->_TYPE, pFly->_SUB_TYPE)] = pFly;
	}

	return true;
}

DungeonRewardData::Flyweight * DungeonRewardData::GetFly(DungeonRewardData::Key & clsKey)
{
	auto iter = clsFlyTree.find(clsKey);

	if (iter == clsFlyTree.end())
		return NULL;

	return iter->second;
}

DungeonRewardData *
DungeonRewardResource::GetRewardPtr(User * pUser)
{
	NUtil::MarketType marketType = NUtil::GetMarketType(pUser->GetUserInfo().company, pUser->GetUserInfo().sale_code);

	switch (marketType)
	{
	case NUtil::MarketType::AD_KAKAO:
		return pDungeonRewardAD;

	case NUtil::MarketType::IOS_KAKAO:
		return pDungeonRewardIOS;

	default:
		return NULL;
	}
}

int DungeonRewardResource::GetItemClassType(User * pUser, int sheetType)
{
	// 장신구인 경우 classtype -1
	if (sheetType >= CLASS_ITEM_TABLE_MAX)
		return -1;

	BalanceData * pBalance = Static::InstancePtr()->GetBalance()->GetBalancePtr(pUser);
	if (NULL == pBalance)
	{
		DEBUGLOG("GetItemClassType : pBalance is NULL!!");
		return 0;
	}

	int accRate		= pBalance->GetValue(EM_CARD_REWARD_OWN_CLASS_RATE);
	int randRate	= rand() % 100;

	// 유저의 클래스 아이템 확률
	if (randRate < accRate)
		return pUser->GetCharacterInfo().classtype;

	int classType = 0;
	//------------------------------------------------------
	// Changed by spencer(2014.07.02)
	// 성기사 클래스 추가 open/close에 따른 처리
	//------------------------------------------------------
	int iClassCount = EnumCharClass::CLASS_TYPE_MAX;
	if ( false == NResource::Static::Instance().GetContentsOpenResource()->IsOpen(ContentsOpen::NEW_CLASS_PALADIN) )
		iClassCount -= 1;

	for (; classType < iClassCount; classType++)
	{
		if (classType == static_cast<int>(pUser->GetCharacterInfo().classtype))
			continue;

		accRate += ceil((100.0 - pBalance->GetValue(EM_CARD_REWARD_OWN_CLASS_RATE)) / (iClassCount - 1));

		if (randRate < accRate)
			break;
	}

	return classType;

//	switch (sheetType)
//	{
//	case CLASS_ITEM_TABLE_WEAPONE:
//	case CLASS_ITEM_TABLE_HELMET:
//	case CLASS_ITEM_TABLE_ARMOR:
//	case CLASS_ITEM_TABLE_GLOVES:
//	case CLASS_ITEM_TABLE_SHOES:
//		classType = rand() % EnumCharClass::CLASS_TYPE_MAX;
//		break;
//
//	default:
//		break;
//	}
//
//	return classType;
}

int DungeonRewardResource::GetItemTid(int minLevel, int maxLevel, int sheetType, int classType)
{
	TIDVECTOR tidvector;

	switch (sheetType)
	{
	// 장비
	case EnumClassItemTableType::CLASS_ITEM_TABLE_WEAPONE:
		this->SetWeapone(minLevel, maxLevel, classType, tidvector);
		break;
	case EnumClassItemTableType::CLASS_ITEM_TABLE_HELMET:
		this->SetHelmet(minLevel, maxLevel, classType, tidvector);
		break;
	case EnumClassItemTableType::CLASS_ITEM_TABLE_ARMOR:
		this->SetArmor(minLevel, maxLevel, classType, tidvector);
		break;
	case EnumClassItemTableType::CLASS_ITEM_TABLE_GLOVES:
		this->SetGloves(minLevel, maxLevel, classType, tidvector);
		break;
	case EnumClassItemTableType::CLASS_ITEM_TABLE_SHOES:
		this->SetShoes(minLevel, maxLevel, classType, tidvector);
		break;

	// 장신구
	case EnumClassItemTableType::CLASS_ITEM_TABLE_NECKLACE:
		this->SetNecklace(minLevel, maxLevel, tidvector);
		break;
	case EnumClassItemTableType::CLASS_ITEM_TABLE_CLOAK:
		this->SetCloak(minLevel, maxLevel, tidvector);
		break;
	case EnumClassItemTableType::CLASS_ITEM_TABLE_RING:
		this->SetRing(minLevel, maxLevel, tidvector);
		break;
	case EnumClassItemTableType::CLASS_ITEM_TABLE_CHARM:
		this->SetCharm(minLevel, maxLevel, tidvector);
		break;
	}

	int tid = 0;
	int vectorSize = static_cast<int>(tidvector.size());

	if (vectorSize > 0)
		tid = tidvector[rand() % vectorSize];

	return tid;
}



void DungeonRewardResource::SetWeapone(int minLevel, int maxLevel, int classType, TIDVECTOR & vector)
{
	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_WEAPONE);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (classType == pair.second->_CHARCLASSTYPE && minLevel <= pair.second->_LIMIT_LEVEL && pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );
//
//
//
//	if (classType == EnumCharClass::CLASS_TYPE_SLASHER)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS1_WEAPON01_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class1_Weapon01[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class1_Weapon01[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
//	else if (classType == EnumCharClass::CLASS_TYPE_RANGER)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS2_WEAPON02_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class2_Weapon02[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class2_Weapon02[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
//	else if (classType == EnumCharClass::CLASS_TYPE_FIGHTER)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS3_WEAPON03_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class3_Weapon03[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class3_Weapon03[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
//	else if (classType == EnumCharClass::CLASS_TYPE_MAGICIAN)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS4_WEAPON04_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class4_Weapon04[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class4_Weapon04[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
//	else if (classType == EnumCharClass::CLASS_TYPE_ASSASSIN)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS5_WEAPON05_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class5_Weapon05[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class5_Weapon05[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
}

void DungeonRewardResource::SetHelmet(int minLevel, int maxLevel, int classType, TIDVECTOR & vector)
{
	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_HELMET);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (classType == pair.second->_CHARCLASSTYPE && minLevel <= pair.second->_LIMIT_LEVEL && pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );

//	if (classType == EnumCharClass::CLASS_TYPE_SLASHER)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS1_HELMET01_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class1_Helmet01[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class1_Helmet01[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
//	else if (classType == EnumCharClass::CLASS_TYPE_RANGER)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS2_HELMET02_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class2_Helmet02[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class2_Helmet02[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
//	else if (classType == EnumCharClass::CLASS_TYPE_FIGHTER)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS3_HELMET03_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class3_Helmet03[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class3_Helmet03[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
//	else if (classType == EnumCharClass::CLASS_TYPE_MAGICIAN)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS4_HELMET04_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class4_Helmet04[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class4_Helmet04[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
//	else if (classType == EnumCharClass::CLASS_TYPE_ASSASSIN)
//	{
//		for (int i = 0; i < NXLData::ITEM_CLASS5_HELMET05_MAX; i++)
//		{
//			if (minLevel <= NXLData::stItem_Class5_Helmet05[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class5_Helmet05[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//		}
//	}
}

void DungeonRewardResource::SetArmor(int minLevel, int maxLevel, int classType, TIDVECTOR & vector)
{
	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_ARMOR);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (classType == pair.second->_CHARCLASSTYPE && minLevel <= pair.second->_LIMIT_LEVEL && pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );

//    if (classType == EnumCharClass::CLASS_TYPE_SLASHER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS1_ARMOR01_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class1_Armor01[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class1_Armor01[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_RANGER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS2_ARMOR02_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class2_Armor02[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class2_Armor02[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_FIGHTER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS3_ARMOR03_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class3_Armor03[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class3_Armor03[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_MAGICIAN)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS4_ARMOR04_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class4_Armor04[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class4_Armor04[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_ASSASSIN)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS5_ARMOR05_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class5_Armor05[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class5_Armor05[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
}

void DungeonRewardResource::SetGloves(int minLevel, int maxLevel, int classType, TIDVECTOR & vector)
{
	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_GLOVES);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (classType == pair.second->_CHARCLASSTYPE && minLevel <= pair.second->_LIMIT_LEVEL && pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );

//    if (classType == EnumCharClass::CLASS_TYPE_SLASHER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS1_GLOVES01_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class1_Gloves01[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class1_Gloves01[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_RANGER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS2_GLOVES02_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class2_Gloves02[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class2_Gloves02[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_FIGHTER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS3_GLOVES03_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class3_Gloves03[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class3_Gloves03[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_MAGICIAN)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS4_GLOVES04_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class4_Gloves04[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class4_Gloves04[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_ASSASSIN)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS5_GLOVES05_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class5_Gloves05[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class5_Gloves05[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
}

void DungeonRewardResource::SetShoes(int minLevel, int maxLevel, int classType, TIDVECTOR & vector)
{
	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_SHOES);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (classType == pair.second->_CHARCLASSTYPE && minLevel <= pair.second->_LIMIT_LEVEL && pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );

//    if (classType == EnumCharClass::CLASS_TYPE_SLASHER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS1_SHOES01_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class1_Shoes01[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class1_Shoes01[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_RANGER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS2_SHOES02_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class2_Shoes02[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class2_Shoes02[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_FIGHTER)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS3_SHOES03_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class3_Shoes03[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class3_Shoes03[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_MAGICIAN)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS4_SHOES04_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class4_Shoes04[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class4_Shoes04[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
//    else if (classType == EnumCharClass::CLASS_TYPE_ASSASSIN)
//    {
//        for (int i = 0; i < NXLData::ITEM_CLASS5_SHOES05_MAX; i++)
//        {
//			if (minLevel <= NXLData::stItem_Class5_Shoes05[i].LIMIT_LEVEL
//					&& NXLData::stItem_Class5_Shoes05[i].LIMIT_LEVEL <= maxLevel)
//			{
//				vector.push_back(i);
//			}
//        }
//    }
}

void DungeonRewardResource::SetNecklace(int minLevel, int maxLevel, TIDVECTOR & vector)
{
//	for (int i = 0; i < NXLData::ITEM_COMMON_COMMON_NECKLACE_MAX; i++)
//	{
//		if (minLevel <= NXLData::stItem_Common_Common_Necklace[i].LIMIT_LEVEL
//				&& NXLData::stItem_Common_Common_Necklace[i].LIMIT_LEVEL <= maxLevel)
//		{
//			vector.push_back(i);
//		}
//	}

	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_NECKLACE);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (minLevel <= pair.second->_LIMIT_LEVEL
				&& pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );
}

void DungeonRewardResource::SetCloak(int minLevel, int maxLevel, TIDVECTOR & vector)
{
//	for (int i = 0; i < NXLData::ITEM_COMMON_COMMONITEM_CLOAK_MAX; i++)
//	{
//		if (minLevel <= NXLData::stItem_Common_Commonitem_Cloak[i].LIMIT_LEVEL
//				&& NXLData::stItem_Common_Commonitem_Cloak[i].LIMIT_LEVEL <= maxLevel)
//		{
//			vector.push_back(i);
//		}
//	}

	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_CLOAK);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (minLevel <= pair.second->_LIMIT_LEVEL
				&& pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );
}

void DungeonRewardResource::SetRing(int minLevel, int maxLevel, TIDVECTOR & vector)
{
//	for (int i = 0; i < NXLData::ITEM_COMMON_COMMONITEM_RING_MAX; i++)
//	{
//		if (minLevel <= NXLData::stItem_Common_Commonitem_Ring[i].LIMIT_LEVEL
//				&& NXLData::stItem_Common_Commonitem_Ring[i].LIMIT_LEVEL <= maxLevel)
//		{
//			vector.push_back(i);
//		}
//	}

	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_RING);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (minLevel <= pair.second->_LIMIT_LEVEL
				&& pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );
}

void DungeonRewardResource::SetCharm(int minLevel, int maxLevel, TIDVECTOR & vector)
{
//	for (int i = 0; i < NXLData::ITEM_COMMON_COMMONITEM_CHARM_MAX; i++)
//	{
//		if (minLevel <= NXLData::stItem_Common_Commonitem_Charm[i].LIMIT_LEVEL
//				&& NXLData::stItem_Common_Commonitem_Charm[i].LIMIT_LEVEL <= maxLevel)
//		{
//			vector.push_back(i);
//		}
//	}

	NResource::ItemResource::ITEMRESOURCETREE & tree
		= NResource::Static::Instance().GetItemResource()->GetItemResourceTree(CLASS_ITEM_TABLE_CHARM);
	std::for_each(tree.begin(), tree.end(), [&](NResource::ItemResource::ITEMRESOURCETREE::value_type & pair) {
		if (minLevel <= pair.second->_LIMIT_LEVEL
				&& pair.second->_LIMIT_LEVEL <= maxLevel)
		{
			vector.push_back(pair.second->_TID);
		}
	} );
}

int DungeonRewardResource::GetItemQuality(User * pUser, DungeonRewardData * pReward, int rewardQuality, int gachyaType)
{
	/*
	 * 아이템의 등급 결정
	 *
	 * rewardQuality
	 * 		0 : GOOD 아이템
	 * 		1 : NORMAL 아이템
	 * 		2 : BAD 아이템
	 *
	 * gachyaType
	 * 		0 : 1성 뽑기
	 * 		1 : 3성 뽑기
	 * 		2 : 4성 뽑기
	 */

	int itemQuality	= 0;
	int accRate		= 0;
	int randRate	= rand() % 1000;

	int type = 0;

	bool bEvent = NResource::Static::InstancePtr()->GetEventTime()->IsDungeonRewardItemQualityEvent(pUser);

	// 1성, 3성 뽑기의 이벤트는 던전 카드 보상에서만 유효.
	// 4성 뽑기는 이벤트 없음

	switch (static_cast<ItemGachyaType>(gachyaType))
	{
	case EM_1_QUALITY_GACHYA:	// 1성 뽑기권
		if (true == bEvent)
			type = static_cast<int>(EM_ITEM_1_QUALITY_RATE_EVENT);
		else
			type = static_cast<int>(EM_ITEM_1_QUALITY_RATE);
		break;

	case EM_3_QUALITY_GACHYA:	// 3성 뽑기권
		if (true == bEvent)
			type = static_cast<int>(EM_ITEM_3_QUALITY_RATE_EVENT);
		else
			type = static_cast<int>(EM_ITEM_3_QUALITY_RATE);
		break;

	case EM_4_QUALITY_GACHYA:	// 4성 뽑기권
		type = static_cast<int>(EM_ITEM_4_QUALITY_RATE);
		break;
	}

	DungeonRewardData::DUNGEONREWARDTREE::const_iterator citer = pReward->GetTree().begin();

	for (; citer != pReward->GetTree().end(); citer++)
	{
		if (type != citer->first.type)
			continue;

		switch (rewardQuality)
		{
		case 0: accRate += citer->second->_VALUE1; break;
		case 1: accRate += citer->second->_VALUE2; break;
		case 2: accRate += citer->second->_VALUE3; break;
		}

		if (randRate < accRate)
		{
			itemQuality = citer->second->_SUB_TYPE;
			break;
		}
	}

	return itemQuality;
}

int DungeonRewardResource::GetItemRefineStep(User * pUser, DungeonRewardData * pReward, int rewardQuality, int gachyaType)
{
	/*
	 * 아이템의 제련 단계 결정
	 *
	 * rewardQuality
	 * 		0 : GOOD 아이템
	 * 		1 : NORMAL 아이템
	 * 		2 : BAD 아이템
	 *
	 * gachyaType
	 * 		0 : 1성 뽑기
	 * 		1 : 3성 뽑기
	 * 		2 : 4성 뽑기
	 */

	int refineStep	= 0;
	int accRate		= 0;
	int randRate	= rand() % 1000;

	int type = 0;

	bool bEvent = NResource::Static::InstancePtr()->GetEventTime()->IsDungeonRewardItemRefineEvent(pUser);

	// 1성, 3성 뽑기의 이벤트는 던전 카드 보상에서만 유효.
	// 4성 뽑기는 이벤트 없음

	switch (static_cast<ItemGachyaType>(gachyaType))
	{
	case EM_1_QUALITY_GACHYA:	// 1성 뽑기권
		if (true == bEvent)
			type = static_cast<int>(EM_ITEM_1_QUALITY_REFINE_RATE_EVENT);
		else
			type = static_cast<int>(EM_ITEM_1_QUALITY_REFINE_RATE);
		break;

	case EM_3_QUALITY_GACHYA:	// 3성 뽑기권
		if (true == bEvent)
			type = static_cast<int>(EM_ITEM_3_QUALITY_REFINE_RATE_EVENT);
		else
			type = static_cast<int>(EM_ITEM_3_QUALITY_REFINE_RATE);
		break;

	case EM_4_QUALITY_GACHYA:	// 4성 뽑기권
		type = static_cast<int>(EM_ITEM_4_QUALITY_REFINE_RATE);
		break;
	}

	DungeonRewardData::DUNGEONREWARDTREE::const_iterator citer = pReward->GetTree().begin();

	for (; citer != pReward->GetTree().end(); citer++)
	{
		if (type != citer->first.type)
			continue;

		switch (rewardQuality)
		{
		case 0: accRate += citer->second->_VALUE1; break;
		case 1: accRate += citer->second->_VALUE2; break;
		case 2: accRate += citer->second->_VALUE3; break;
		}

		if (randRate < accRate)
		{
			refineStep = citer->second->_SUB_TYPE;
			break;
		}
	}

	return refineStep;
}

bool DungeonRewardResource::DungeonRewardReady(User * pUser)
{
	DungeonRewardData * pReward = this->GetRewardPtr(pUser);
	if (NULL == pReward)
	{
		DEBUGLOG("%s : pReward is NULL!!", __FUNCTION__);
		return false;
	}

	NLogic::Card * pCard = pUser->GetCard();
	if (NULL == pCard)
	{
		DEBUGLOG("%s : pCard is NULL!!", __FUNCTION__);
		return false;
	}

	pCard->Clear();

	std::vector<int> sheetVector;
	sheetVector.push_back(CLASS_ITEM_TABLE_WEAPONE);	// 무기
	sheetVector.push_back(NUtil::GetRandBetween(CLASS_ITEM_TABLE_HELMET, CLASS_ITEM_TABLE_SHOES));	// 방어구
	sheetVector.push_back(NUtil::GetRandBetween(CLASS_ITEM_TABLE_NECKLACE, CLASS_ITEM_TABLE_CHARM));// 장신구

	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
	{
		DEBUGLOG("%s : pSpace is NULL!!", __FUNCTION__);
		return false;
	}

	// 던전 데이터 lookup
	NResource::DungeonData::Flyweight * pFly =
			NResource::Static::InstancePtr()->GetDungeon()->GetFly(pUser->GetUserInfo().company, pUser->GetUserInfo().sale_code, pSpace->GetData()._table_id);

	if (NULL == pFly)
	{
		DEBUGLOG("%s : pFly is NULL!!", __FUNCTION__);
		return false;
	}

	// 아이템 TID 결정을 위한 최소/최대 레벨
	int bossLv = 0;
	switch (pSpace->GetData()._difficulty)
	{
	case 0: bossLv = pFly->BOSS_LV_NORMAL;	break;
	case 1: bossLv = pFly->BOSS_LV_HARD;	break;
	case 2: bossLv = pFly->BOSS_LV_HELL;	break;
	}

	int maxLevel = bossLv + 2;
	int minLevel = (bossLv - 8) >= 0 ? (bossLv - 8) : 0;

	// 일반 카드 보상 아이템
	std::random_shuffle(sheetVector.begin(), sheetVector.end());

	int sIndex = static_cast<int>(NLogic::Card::CardItemType::CARD_ITEM_TYPE_GOOD);
	int eIndex = static_cast<int>(NLogic::Card::CardItemType::CARD_ITEM_TYPE_BAD);
	int gachyaType = static_cast<int>(ItemGachyaType::EM_1_QUALITY_GACHYA);

	for ( ; sIndex <= eIndex; sIndex++)
	{
		NLogic::Card::Data * pData = new NLogic::Card::Data;

		pData->sheetType	= sheetVector[sIndex];
		pData->classType	= this->GetItemClassType(pUser, pData->sheetType);
		pData->quality		= this->GetItemQuality(pUser, pReward, sIndex, gachyaType);
		pData->refine		= this->GetItemRefineStep(pUser, pReward, sIndex, gachyaType);
		pData->tid			= this->GetItemTid(minLevel, maxLevel, pData->sheetType, pData->classType);

		NResource::Static::InstancePtr()->GetItemResource()->setItemEffectForCardReward(pData);

		pCard->AddNormalCardData(static_cast<NLogic::Card::CardItemType>(sIndex), pData);
	}

	// ZEN 카드 보상 아이템
	std::random_shuffle(sheetVector.begin(), sheetVector.end());

	sIndex = static_cast<int>(NLogic::Card::CardItemType::CARD_ITEM_TYPE_GOOD);
	eIndex = static_cast<int>(NLogic::Card::CardItemType::CARD_ITEM_TYPE_BAD);
	gachyaType = static_cast<int>(ItemGachyaType::EM_3_QUALITY_GACHYA);

	for ( ; sIndex <= eIndex; sIndex++)
	{
		NLogic::Card::Data * pData = new NLogic::Card::Data;

		pData->sheetType	= sheetVector[sIndex];
		pData->classType	= this->GetItemClassType(pUser, pData->sheetType);
		pData->quality		= this->GetItemQuality(pUser, pReward, sIndex, gachyaType);
		pData->refine		= this->GetItemRefineStep(pUser, pReward, sIndex, gachyaType);
		pData->tid			= this->GetItemTid(minLevel, maxLevel, pData->sheetType, pData->classType);

		NResource::Static::InstancePtr()->GetItemResource()->setItemEffectForCardReward(pData);

		pCard->AddZenCardData(static_cast<NLogic::Card::CardItemType>(sIndex), pData);
	}

	return true;
}

int
DungeonRewardResource::GetItemQualityIndex(User * pUser, int gachyaType)
{
	/*
	 * 아이템 품질 결정
	 */
	DungeonRewardData * pReward = this->GetRewardPtr(pUser);
	if (NULL == pReward)
	{
		DEBUGLOG("%s : pReward is NULL!!", __FUNCTION__);
		return -1;
	}

	bool bEvent = NResource::Static::InstancePtr()->GetEventTime()->IsDungeonRewardItemGradeEvent(pUser);

	DungeonRewardData::Key clsKey;

	switch (static_cast<ItemGachyaType>(gachyaType))
	{
	case EM_1_QUALITY_GACHYA:
		if (true == bEvent)
		{
			clsKey.type = static_cast<int>(EM_ACQUIRE_RATE_EVENT);
			clsKey.sub_type = 0;
		}
		else
		{
			clsKey.type = static_cast<int>(EM_ACQUIRE_RATE);
			clsKey.sub_type = 0;
		}
		break;

	case EM_3_QUALITY_GACHYA:
		if (true == bEvent)
		{
			clsKey.type = static_cast<int>(EM_ACQUIRE_RATE_EVENT);
			clsKey.sub_type = 1;
		}
		else
		{
			clsKey.type = static_cast<int>(EM_ACQUIRE_RATE);
			clsKey.sub_type = 1;
		}
		break;

	case EM_4_QUALITY_GACHYA:
		clsKey.type = static_cast<int>(EM_ACQUIRE_RATE);
		clsKey.sub_type = 2;
		break;

	}


	DungeonRewardData::Flyweight * pFly = pReward->GetFly(clsKey);

	if (NULL == pFly)
	{
		DEBUGLOG("%s : pFly is NULL!!", __FUNCTION__);
		return -1;
	}

	int index		= 0;
	int accRate		= 0;
	int randRate	= rand() % 1000;
	for ( ; index < 3; index++)
	{
		switch (index)
		{
		case 0: accRate += pFly->_VALUE1; break;	// Good 등급 아이템 획득 확률
		case 1: accRate += pFly->_VALUE2; break;	// Normal 등급 아이템 획득 확률
		case 2: accRate += pFly->_VALUE3; break;	// Bad 등급 아이템 획득 확률
		}

		if (randRate < accRate)
			break;
	}

	return index;
}


bool
DungeonRewardResource::ItemGachyaReady(User * pUser, int gachyaType)
{
	/*
	 * 아이템 뽑기로 아이템을 뽑는다.
	 *
	 * gachyaType
	 * 	0 : 1성 이상 뽑기권
	 * 	1 : 3성 이상 뽑기권
	 * 	2 : 4성 이상 뽑기권
	 */
	DungeonRewardData * pReward = this->GetRewardPtr(pUser);
	if (NULL == pReward)
	{
		DEBUGLOG("%s : pReward is NULL!!", __FUNCTION__);
		return false;
	}

	NLogic::Card * pCard = pUser->GetCard();
	if (NULL == pCard)
	{
		DEBUGLOG("%s : pCard is NULL!!", __FUNCTION__);
		return false;
	}

	pCard->Clear();

	std::vector<int> sheetVector;
	sheetVector.push_back(CLASS_ITEM_TABLE_WEAPONE);	// 무기
	sheetVector.push_back(NUtil::GetRandBetween(CLASS_ITEM_TABLE_HELMET, CLASS_ITEM_TABLE_SHOES));	// 방어구
	sheetVector.push_back(NUtil::GetRandBetween(CLASS_ITEM_TABLE_NECKLACE, CLASS_ITEM_TABLE_CHARM));// 장신구

	int minLevel = pUser->GetCharacterInfo().level - 10;
	int maxLevel = pUser->GetCharacterInfo().level + 10;

	if (0 >= minLevel)
		minLevel = 1;

	int limitLevel = Static::InstancePtr()->GetCommon()->GetLimitLevel(pUser);
	if (-1 == limitLevel)
	{
		DEBUGLOG("%s : limitLevel get fail.", __FUNCTION__);
		return false;
	}

	if (limitLevel < maxLevel)
		maxLevel = limitLevel;

	std::random_shuffle(sheetVector.begin(), sheetVector.end());

	int sIndex = static_cast<int>(NLogic::Card::CardItemType::CARD_ITEM_TYPE_GOOD);
	int eIndex = static_cast<int>(NLogic::Card::CardItemType::CARD_ITEM_TYPE_BAD);

	for ( ; sIndex <= eIndex; sIndex++)
	{
		NLogic::Card::Data * pData = new NLogic::Card::Data;

		pData->sheetType	= sheetVector[sIndex];
		pData->classType	= this->GetItemClassType(pUser, pData->sheetType);
		pData->quality		= this->GetItemQuality(pUser, pReward, sIndex, gachyaType);
		pData->refine		= this->GetItemRefineStep(pUser, pReward, sIndex, gachyaType);
		pData->tid			= this->GetItemTid(minLevel, maxLevel, pData->sheetType, pData->classType);

		NResource::Static::InstancePtr()->GetItemResource()->setItemEffectForCardReward(pData);

		pCard->AddZenCardData(static_cast<NLogic::Card::CardItemType>(sIndex), pData);
	}

	return true;
}

} /*NResource*/ } /* namespace ProjectZ */
